package com.example.stock.business;

import com.example.stock.common.Constants;
import com.example.stock.controller.dto.MonthPctStatDTO;
import com.example.stock.controller.dto.WeekLowStaDTO;
import com.example.stock.controller.dto.WeekPctStatDTO;
import com.example.stock.controller.vo.StockInfoVO;
import com.example.stock.excel.*;
import com.example.stock.model.DailyDetail;
import com.example.stock.model.DailyGBSta;
import com.example.stock.model.GBSta;
import com.example.stock.model.WeekDetail;
import com.example.stock.service.*;
import com.example.stock.service.impl.GBStaServiceImpl;
import com.example.stock.util.DataUtil;
import com.example.stock.util.GBStaConstant;
import com.example.stock.util.StocksRollSearchEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
public class StockNameBusiness {

    @Autowired
    ArticleDataService articleDataService;

    @Autowired
    StockService stockService;

    @Autowired
    GBStaService gbStaService;

    @Autowired
    StockOperationService stockOperationService;

    @Autowired
    IndustryDataService industryDataService;

    @Autowired
    WeekDataService weekDataService;

    @Autowired
    DailyGBStaService dailyGBStaService;

    @Autowired
    DailyDeSumService dailyDeSumService;

    @Autowired
    DailyMonitorService dailyMonitorService;

    @Autowired
    WeekLowStaBusiness weekLowStaBusiness;

    @Autowired
    MonthDataService monthDataService;

    @Autowired
    DailyDataService dailyDataService;

    @Autowired
    StockDailyMonitorService stockDailyMonitorService;

    @Autowired
    StockWeekMonitorService stockWeekMonitorService;

    @Autowired
    LevelPointService levelPointService;

    @Autowired
    RankService rankService;

    private List<String> categoryFilter(List<String> stocks, String category) {
        return stocks.stream().filter(i -> {
            StockInfoVO stockInfo = stockService.getStockInfo(i);
            if (stockInfo == null) {
                return false;
            }
            return stockInfo.getCategory().equals(category);
        }).toList();
    }

    public List<String> getRollStockName(String search) {

        List<String> stocks = null;

        String[] split = search.split(DataUtil.STOCK_SPLIT);
        String op = split[0];

        String date;
        switch (op) {
            case "指数":
            case "ETF":
            case "股票":
                if(split.length == 2) {
                    stocks = dailyDataService.getLastedDailyDataByDate().stream()
                            .filter(i -> i.getCategory().equals(op))
                            .sorted(Comparator.comparing(DailyDetail::getPct))
                            .map(DailyDetail::getStock).toList();
                } else {
                    // 倒序
                    stocks = dailyDataService.getLastedDailyDataByDate().stream()
                            .filter(i -> i.getCategory().equals(op))
                            .sorted(Comparator.comparing(DailyDetail::getPct).reversed())
                            .map(DailyDetail::getStock).toList();
                }
                break;
            case "BASE":
                stocks = Constants.getBaseStocks();
                break;
            case "RANK":
                stocks = rankService.getStocksByRank();
                break;
            case GBStaConstant.OP_60W_UP:
            case GBStaConstant.OP_30W_UP:
            case GBStaConstant.OP_20W_UP:
                StocksRollSearchEnum OP = StocksRollSearchEnum.getByOP(op);
                if(split.length == 2) {
                    String category = split[1];
                    stocks = gbStaService.getLastGBStaList(OP.getSourceType(), 600).stream()
                            .filter(i -> i.getDisPct() >= 0)
                            .filter(i -> i.getGb60wPct() >= 0)
                            .filter(i -> i.getCategory().equals(category))
                            .map(GBSta::getStock).distinct().toList();
                } else {
                    stocks = gbStaService.getLastGBStaList(OP.getSourceType(), 600).stream()
                            .filter(i -> i.getDisPct() >= 0)
                            .filter(i -> i.getGb60wPct() >= 0)
                            .map(GBSta::getStock).distinct().toList();
                }
                break;
            case "PRO_OPT":  // 高手操作
                List<StockOperate> stockOperationData = stockOperationService.getLastedOperationData(5000);
                stocks = stockOperationData.stream().filter(i -> i.getIndicator() != null && i.getIndicator().equals("高手操作"))
                        .map(StockOperate::getStock).distinct().toList();
                break;
            case "LAST_OPT":  // 最近操作
                if (split.length == 1) {
                    stocks = stockOperationService.getLastedOperationStocks(2000);
                } else if (split.length == 2) {
                    String category = split[1];
                    if (Arrays.asList("ETF","股票").contains(category)) {
                        stocks = stockOperationService.getLastedOperationStocks(2000);
                        stocks = categoryFilter(stocks, category);
                    } else {
                        // 按指标搜索
                        List<StockOperate> lastedOperationData = stockOperationService.getLastedOperationData(2000);
                        stocks = lastedOperationData.stream().filter(i -> i.getIndicator() != null && i.getIndicator().equals(category)).map(StockOperate::getStock).distinct().toList();
                    }
                }
                break;
            case "STOCK_HOLD" :
                List<DailyDetail> ret = new ArrayList<>();
                stockOperationService.getStockHold().forEach(stock -> {
                    DailyDetail lastTradingRankByStock = dailyDataService.getLastedDailyDetailByStock(stock);
                    ret.add(lastTradingRankByStock);
                });
                stocks = ret.stream().sorted(Comparator.comparing(DailyDetail::getPct).reversed())
                        .map(DailyDetail::getStock).distinct().toList();
                if (split.length == 2) {
                    String category = split[1];
                    stocks = categoryFilter(stocks, category);
                }
                break;
            case "STOCKS" :  // 按股票名查询
                stocks = List.of(Arrays.copyOfRange(split, 1, split.length));
                break;
            case "INDUSTRY":  // 按行业
                String industry = split[1];
                stocks = industryDataService.getStocksByTag(industry);
                break;
            case "D_LP_FH":
                stocks = stockDailyMonitorService.getStockDailyMonitors().stream()
                        .filter(i -> i.getType().equals("LP首次新高"))
                        .sorted(Comparator.comparing(StockDailyMonitor::getDate).reversed())
                        .map(StockDailyMonitor::getStock).distinct().toList();
                break;
            case "W_LP_FH":
                stocks = stockWeekMonitorService.getStockWeekMonitors().stream()
                        .filter(i -> i.getType().equals("LP首次新高"))
                        .sorted(Comparator.comparing(StockWeekMonitor::getDate).reversed())
                        .map(StockWeekMonitor::getStock).distinct().toList();
                break;
            case "LP" :
                String week = split[1];
                int lp =  Integer.parseInt(split[2]);
                stocks = levelPointService.getByWeekAndLp(week, lp).stream()
                        .map(WeekDetail::getStock).distinct().toList();
                break;
            case "LP_TOP" :
                date = weekDataService.getWeekPctStatKeys().getFirst();
                stocks = weekDataService.getWeekRawDataByDate(date).stream()
                        .sorted(Comparator.comparing(WeekDetail::getLp).reversed())
                        .map(WeekDetail::getStock)
                        .limit(200)
                        .toList();
                break;
            case "LP_LOW":
                date = weekDataService.getWeekPctStatKeys().getFirst();
                stocks = weekDataService.getWeekRawDataByDate(date).stream()
                        .sorted(Comparator.comparing(WeekDetail::getLp))
                        .map(WeekDetail::getStock)
                        .limit(200)
                        .toList();
                break;
            case GBStaConstant.OP_20D_UP:
                stocks = dailyGBStaService.getLastUpDailyGBSta(GBStaConstant.DAILY_TYPE_20, 300).stream().map(DailyGBSta::getStock).distinct().toList();
                break;
            case GBStaConstant.OP_30D_UP:
                stocks = dailyGBStaService.getLastUpDailyGBSta(GBStaConstant.DAILY_TYPE_30, 300).stream().map(DailyGBSta::getStock).distinct().toList();
                break;
            case GBStaConstant.OP_60D_UP:
                stocks = dailyGBStaService.getLastUpDailyGBSta(GBStaConstant.DAILY_TYPE_60, 300).stream().map(DailyGBSta::getStock).distinct().toList();
                break;
            case GBStaConstant.OP_100D_UP:
                stocks = dailyGBStaService.getLastUpDailyGBSta(GBStaConstant.DAILY_TYPE_100, 300).stream().map(DailyGBSta::getStock).distinct().toList();
                break;
            case GBStaConstant.OP_300D_UP:
                stocks = dailyGBStaService.getLastUpDailyGBSta(GBStaConstant.DAILY_TYPE_300, 300).stream().map(DailyGBSta::getStock).distinct().toList();
                break;
            case "60W_TOP" :
                stocks = gbStaService.getDurGtList(GBStaServiceImpl.GB_60W_K, 60)
                        .stream().map(GBSta::getStock).distinct()
                        .limit(350).toList();
                if (split.length == 2) {
                    String category = split[1];
                    stocks = categoryFilter(stocks, category);
                }
                break;
            case "DE_SUM" :
                stocks = dailyDeSumService.getLatestDailyDeSum(450).stream().map(DailyDeSum::getStock).distinct().toList();
                break;
            case "DAILY_MONITOR" :
                date = split[1];
                stocks = dailyMonitorService.getDataByMonitorDate(date).stream()
                        .map(DailyMonitor::getStock)
                        .limit(300).toList();
                if (split.length == 3) {
                    String category = split[2];
                    stocks = categoryFilter(stocks, category);
                }
                break;
            case "LAST_ARTICLE" :
                stocks = articleDataService.getLatestArticle().stream().map(Article::getTag).distinct().toList();
                break;
            case "MONTH_PCT":
                String month = split[1];
                if (split.length == 3) {
                    stocks = monthDataService.getMonthPctStatByDate(month).stream()
                            .sorted(Comparator.comparing(MonthPctStatDTO::getMonthPct))
                            .map(MonthPctStatDTO::getStock).limit(100).toList();
                } else {
                    stocks = monthDataService.getMonthPctStatByDate(month).stream()
                            .sorted(Comparator.comparing(MonthPctStatDTO::getMonthPct).reversed())
                            .map(MonthPctStatDTO::getStock).limit(100).toList();
                }
                break;
            case "LOW_STA": // 新低
                stocks= weekLowStaBusiness.getWeekLowSta().stream()
                        .sorted(Comparator.comparing(WeekLowStaDTO::getDisPct))
                        .map(WeekLowStaDTO::getStock)
                        .limit(200).toList();
                break;
            case "60W_DIS":
                List<WeekPctStatDTO> weekPctStatList = weekDataService.getWeekPctStatList(weekDataService.getWeekPctStatKeys().getFirst());
                if (split.length == 2) {
                    switch (split[1]) {
                        case "n_asc" -> stocks = weekPctStatList.stream().sorted(Comparator.comparing(WeekPctStatDTO::getDisPct))
                                                .filter(i -> i.getDisPct() < 0)
                                                .map(WeekPctStatDTO::getStock)
                                                .toList();
                        case "n_desc" -> stocks = weekPctStatList.stream().sorted(Comparator.comparing(WeekPctStatDTO::getDisPct).reversed())
                                                .filter(i -> i.getDisPct() < 0)
                                                .map(WeekPctStatDTO::getStock)
                                                .toList();
                        case "p_desc" -> stocks = weekPctStatList.stream().sorted(Comparator.comparing(WeekPctStatDTO::getDisPct).reversed())
                                                .filter(i -> i.getDisPct() >= 0)
                                                .map(WeekPctStatDTO::getStock)
                                                .toList();
                    }
                } else {
                    stocks = weekPctStatList.stream().sorted(Comparator.comparing(WeekPctStatDTO::getDisPct))
                            .filter(i -> i.getDisPct() >= 0)
                            .map(WeekPctStatDTO::getStock)
                            .toList();
                }
                break;
        }
        return stocks;
    }
}
